package com.panfeng.xcloud.gateway.reptile;

import com.panfeng.xcloud.common.core.utils.RSACoder;
import com.panfeng.xcloud.common.core.utils.SpringContextUtil;
import com.panfeng.xcloud.common.core.utils.StringUtils;
import com.panfeng.xcloud.gateway.config.AntiCrawlerPropConfig;
import lombok.extern.slf4j.Slf4j;

/**
 * url-rsa反爬虫验证规则
 *
 * @author xiaobo
 * @version 1.0
 * @since 2019-05-21
 */
@Slf4j
public class UrlRsaAntiCrawlerRule extends AntiCrawlerRule {

    @Override
    public boolean antiCheck(String checkContent, String toBeCheckContent) {
        if (StringUtils.isEmpty(checkContent) || StringUtils.isEmpty(toBeCheckContent)){
            log.info(">>> 当期反爬虫验证内容为空直接返回，验证失败 <<<");
            return false;
        }
        AntiCrawlerPropConfig antiCrawlerPropConfig = SpringContextUtil.getApplicationContext().getBean(AntiCrawlerPropConfig.class);
        if(null == antiCrawlerPropConfig){
            log.info(">>> 无法从spring上下文获取到反爬虫配置信息,请检查服务端配置 <<<");
            return false;
        }
        String privateKey = antiCrawlerPropConfig.getPrivateKey();
        String publicKey = antiCrawlerPropConfig.getPublicKey();
        log.info(">>>> 配置中的公钥: {} <<<<",publicKey);
        log.info(">>>> 配置中的私钥：{} <<<<",privateKey);
        if(StringUtils.isEmpty(privateKey)){
            log.info(">>> 当前服务未配置私钥，直接返回验证失败,请检查服务端配置 <<<");
            return false;
        }
        byte[] decodedData = null;
        try {
            decodedData = RSACoder.decryptByPrivateKey(checkContent,privateKey);
        } catch (Exception e) {
            log.error(">>> 解密异常:{} <<<",e.getMessage());
            e.printStackTrace();
            return false;
        }
        if (null == decodedData){
            log.error(">>> 解密数据为空，直接返回验证失败 <<<");
            return false;
        }
        String outputString = new String(decodedData);
        log.info(">>> 加密前:{} <<<",toBeCheckContent);
        log.info(">>> 解密后:{} <<<",outputString);
        boolean isCheck = toBeCheckContent.equals(outputString);
        log.info(">>> 反爬虫验证结果:{} <<<",isCheck);
        return isCheck;
    }

    @Override
    public boolean antiCheck(String checkContent) {
        if (StringUtils.isEmpty(checkContent) ){
            log.info(">>> 当期反爬虫验证内容为空直接返回，验证失败 <<<");
            return false;
        }
        AntiCrawlerPropConfig antiCrawlerPropConfig = SpringContextUtil.getApplicationContext().getBean(AntiCrawlerPropConfig.class);
        if(null == antiCrawlerPropConfig){
            log.info(">>> 无法从spring上下文获取到反爬虫配置信息,请检查服务端配置 <<<");
            return false;
        }
        String privateKey = antiCrawlerPropConfig.getPrivateKey();
        String publicKey = antiCrawlerPropConfig.getPublicKey();
        log.info(">>>> 配置中的公钥: {} <<<<",publicKey);
        log.info(">>>> 配置中的私钥：{} <<<<",privateKey);
        if(StringUtils.isEmpty(privateKey)){
            log.info(">>> 当前服务未配置私钥，直接返回验证失败,请检查服务端配置 <<<");
            return false;
        }
        byte[] decodedData = null;
        try {
            decodedData = RSACoder.decryptByPrivateKey(checkContent,privateKey);
        } catch (Exception e) {
            log.error(">>> 解密异常:{} <<<",e.getMessage());
            e.printStackTrace();
            return false;
        }
        if (null == decodedData){
            log.error(">>> 解密数据为空，直接返回验证失败 <<<");
            return false;
        }
        String outputString = new String(decodedData);
        log.info(">>> 解密后:{} <<<",outputString);
        /** 其中 antiKey 的内容格式是： clientSecret：timestamp(精确的毫秒) **/
        if(outputString.indexOf(":") == -1){
            log.error(">>> 当前传过来的内容格式不正确:{} <<<",outputString);
            return false;
        }
        String[] outputStringSplit = outputString.split(":");
        if(outputStringSplit.length != 2){
            log.error(">>> 当前传过来的内容格式不正确:{} <<<",outputString);
            return false;
        }
        //1、校验时间戳是否超时
        Long intervalTime = antiCrawlerPropConfig.getIntervalTime();
        String timeTampForReq = outputString.split(":")[1];
        Long intervalTimeForReq = System.currentTimeMillis() - Long.valueOf(timeTampForReq);
        if (intervalTimeForReq > intervalTime){
            log.error(">>> 当前传过来的信息已失效，有效时间区间intervalTime:{} <<<",intervalTime);
            return false;
        }
        //2、校验秘钥
        String clientSecretForReq = outputString.split(":")[0];
        String clientSecret = antiCrawlerPropConfig.getClientSecret();
        boolean isCheck = clientSecret.equals(clientSecretForReq);
        log.info(">>> 反爬虫验证结果:{} <<<",isCheck);
        return isCheck;
    }
}
